home *** CD-ROM | disk | FTP | other *** search
- #ifndef FWCHARIT_H
- #define FWCHARIT_H
- //========================================================================================
- //
- // File: FWCharIt.h
- // Release Version: $ 1.0d11 $
- //
- // Copyright: (c) 1993, 1995 by Apple Computer, Inc., all rights reserved.
- //
- //========================================================================================
-
- #ifndef FWAUTODE_H
- #include "FWAutoDe.h"
- #endif
-
- #ifndef FWPRIDEB_H
- #include "FWPriDeb.h"
- #endif
-
- #ifndef FWCHARAC_H
- #include "FWCharac.h"
- #endif
-
- #if FW_LIB_EXPORT_PRAGMAS
- #pragma lib_export on
- #endif
-
- #define FW_DEBUG_TEXT_ITERATORS
-
-
- //========================================================================================
- // Design Notes for Text Readers
- //
- // Text readers are designed to be as fast and light-weight as possible. We assume
- // that in over 90% of the usage of Text readers, the reader will be used to make
- // one sequential pass through the data structure, operating on one character at a time.
- // The first design goal is therefore:
- // 1) Make GetCharacterAndAdvance be as efficient as possible.
- // In order to achieve full efficiency, we need to minimize overhead for error checking
- // for reading past the end of the data structure. We therefore set this requirement:
- // 2) Rely on a clear contract to minimize overhead. It is not necessary for
- // iterators to fail gracefully when misused.
- // As stated above, in 90% of the cases, the text is read in one forward pass. However,
- // reading backward through the text is a surprisingly large portion of the remaining
- // 10%, and if not supported, significantly reduces the usefulness of readers. We
- // therefore attempt to achieve this goal:
- // 3) Make "put back" a relatively efficient operation. Make it possible to
- // read backwards through the data structure.
- // Often a client iterating over text will want to note the position of some character
- // or token in the text. We therefore set another goal:
- // 4) Support GetPosition ('tell') and SetPosition ('seek') operations.
- // This last goal implies a specific need to handle the case where a client attempts to
- // seek past the end of the text data structure. In this case, to achieve efficiency,
- // we invoke 2), by setting this requirement:
- // 5) It is acceptable to state in the contract that an attempt to SetPosition to
- // an arbitrary position may fail. However, a client can use GetLength to find
- // the length of the data structure; it is safe to SetPosition to any value greater
- // than or equal to zero, and less than the length of the data structure.
- //========================================================================================
-
- //========================================================================================
- // CLASS FW_CTextReader
- //
- // A base class for iterators that read over a data structure containing characters.
- //
- // It is possible to create a TextReader to read over any text data structure, as long
- // as the following constraints are met:
- //
- // 1) It must be possible to get the total number of characters in the data structure
- // at the time the text reader is constructed.
- // 1a) Of course, we assume that the length and content of the data structure does
- // not change while the iterator is being used!
- // 2) The data members fStart, fLimit, and fNext are updated
- //
- //
- // Invariant:
- // ((fStart<=fNext) && (fNext<fLimit))
- // || ((fStart-1==fNext) && (fBufferSum==0))
- // || ((fNext==fLimit) && (fBufferSum==GetLength())
- //========================================================================================
-
- class FW_CLASS_ATTR FW_CTextReader FW_AUTO_DESTRUCT_OBJECT
- {
-
- public:
-
- // ----- General
-
- virtual ~ FW_CTextReader();
- FW_CTextReader(const FW_Byte* chunk1Start, // start of first contiguous chunk
- const FW_Byte* chunk1Limit, // limit of first contiguous chunk
- FW_ByteCount totalLength); // total bytes in data structure
-
- FW_ByteCount GetPosition(FW_Boolean inChars = FALSE);
- // Get the current byte or character position, where 0 is first position in data structure.
-
- void SetPosition(FW_ByteCount position);
- // Set the byte position to position.
- // The result is undefined if position is outside the bounds of the data structure.
-
- virtual FW_CharacterCount GetLength();
- // Get number of characters in data structure.
-
- FW_ByteCount GetByteLength();
- // Get number of bytes in data structure.
-
- const FW_Byte* PeekByte() const;
- // Return a pointer to the current byte without advancing. Can be used for lookahead.
-
- // ----- Byte-by-byte iteration
-
- FW_Char PeekCharacter();
- // Return the current character (byte) without advancing.
- // Can be used for lookahead.
-
- FW_Char GetCharacterAndAdvance();
- // Get the current character (byte) and advance.
-
- FW_Char BackupAndGetCharacter();
- // Backup and get previous character (byte).
-
- // ----- Character-by-character iteration
-
- void Advance();
- // Advance by one character.
-
- void Backup();
- // Backup by one character.
-
- FW_LChar GetCharacterAndAdvance(FW_ByteCount& bytesInChar);
- // Get the current character and advance.
-
- virtual FW_LChar PeekCharacter(FW_ByteCount& bytesInChar);
- // Return the current character without advancing.
- // Assumes all input characters are the same width (fBytesPerChar).
- // Override to handle variable-width characters.
-
- virtual FW_LChar BackupAndGetCharacter(FW_ByteCount& bytesInChar);
- // Backup and get previous character.
- // Assumes all input characters are the same width (fBytesPerChar).
- // Override to handle variable-width characters.
-
- // ----- Chunky iteration
- // With chunky iteration, client is responsible for translating between bytes and characters.
- // The member functions FW_CTextReader::CharactersInBlock and FW_CTextReader::BytesToChars
- // may be used to do the translation.
-
- void Advance(FW_ByteCount delta);
- // Advance by delta bytes.
-
- void Backup(FW_ByteCount delta);
- // Backup by delta bytes.
-
- void PeekRunAhead(const FW_Byte*& start, FW_ByteCount& length);
- // Peek ahead into current buffer of bytes without advancing.
-
- void PeekRunBehind(const FW_Byte*& end, FW_ByteCount& length);
- // Peek behind into current buffer of bytes without backing up.
- // end points one past "current" byte!
-
- protected:
-
- void GetNextBuffer();
- // Calls DoGetNextBuffer, and updates fNext, fBufferSum.
-
- void GetPreviousBuffer();
- // Calls DoGetPreviousBuffer, and updates fNext, fBufferSum.
-
- virtual void DoGetNextBuffer() = 0;
- // Get another buffer from text data structure.
- // Updates fStart and fLimit.
- // Must ensure that fStart<=fLimit.
-
- virtual void DoGetPreviousBuffer() = 0;
- // Gets previous buffer from text data structure.
- // Updates fStart and fLimit.
- // Must ensure that fStart<=fLimit.
-
- virtual FW_CharacterCount CharactersInBlock(const FW_Byte* last,
- const FW_Byte* first);
-
- const FW_Byte* PreviousByte(const FW_Byte* current, short delta);
-
- virtual FW_CharacterCount BytesToChars(const FW_ByteCount bytes);
-
- FW_ByteCount CharsToBytes(FW_CharacterCount length);
-
- FW_ByteCount BytesInBlock(const FW_Byte* last, const FW_Byte* first);
-
-
- const FW_Byte *fStart; // Start of current buffer
-
- const FW_Byte *fLimit; // One past last byte of current buffer
-
- FW_ByteCount fByteLength; // Total bytes in data structure.
-
- FW_ByteCount fBytesPerChar; // Default value is sizeof(FW_Char)
-
- private:
-
- const FW_Byte *fNext; // Current position in buffer
-
- #ifdef FW_DEBUG_TEXT_ITERATORS
- void ClassInvariants() const;
- #else
- void ClassInvariants() const {} // Let compiler optimize away the empty inline
- #endif
-
- FW_ByteCount fBufferSum; // Total bytes in previous buffers.
- };
-
- //========================================================================================
- // CLASS FW_CTextWriter
- //
- // TextWriters are (intentionally) kept simpler than TextReaders. We assume that there
- // is no need to allow backing up in order to rewrite. This results in a smaller and
- // simpler interface.
- //========================================================================================
-
- enum FW_TextWriterMode {FW_kTextWriteOver, FW_kTextAppend};
-
- class FW_CLASS_ATTR FW_CTextWriter FW_AUTO_DESTRUCT_OBJECT
- {
- public:
-
- // ----- General
-
- virtual ~ FW_CTextWriter();
- // Flush the current buffer.
- // Writer destructors must do whatever may be necessary to restore text structure
- // to valid state, e.g. restore NUL termination, cached length member, etc.
-
- FW_CTextWriter(FW_Byte *chunk1Start, // start of first contiguous chunk
- FW_Byte *chunk1Limit);// limit of first contiguous chunk
-
- FW_CharacterCount GetPosition();
- // Get the current position, in characters.
-
- virtual void FlushAndUpdateText();
- // Flush the current buffer.
- // Call this method when done writing, or in the destructor.
- // Override to do whatever may be necessary to restore the
- // text data structure to a valid state.
-
- // ----- Character-by-character iteration
-
- void PutCharacterAndAdvance(FW_Char character);
- // Write the character (byte) into the data structure and advance to next position.
-
- void PutCharacterAndAdvance(FW_LChar character, FW_ByteCount bytesInChar=0);
- // Write the character into the data structure and advance to next position.
- // Pass 0 for bytesInChar to use the default character size (fBytesPerChar)
-
- // ----- Chunky iteration
-
- void WritePeek(FW_Byte*& start, FW_ByteCount& length);
- // Returns start address and length of buffer to write into.
-
- void WritePeekAdvance(const FW_Byte* start, FW_ByteCount bytesWritten);
- // Inform iterator of number of bytes written into peek buffer
- // start value must be same as returned by WritePeek
- // No calls to PutCharacterAndAdvance between WritePeek and WritePeekAdvance!
-
- protected:
-
- virtual FW_CharacterCount BytesToChars(const FW_ByteCount bytes);
-
- virtual FW_CharacterCount CharactersInBlock(const FW_Byte* last,
- const FW_Byte* first);
-
- virtual void DoFlushBuffer(FW_ByteCount bytesToFlush) = 0;
- // Flush the current buffer.
-
- virtual void DoGetNextBuffer() = 0;
- // Get another buffer from text data structure, update fNext and fLimit.
-
- void FlushBuffer(FW_Boolean flushAll);
- // Calls DoFlushBuffer to flush the current buffer, and updates fBufferSum.
-
- void FlushAndGetNextBuffer();
- // Calls FlushBuffer and DoGetNextBuffer.
- // Called when the buffer has filled up.
-
- FW_ByteCount fBufferSum; // Total characters flushed in previous buffers.
- FW_Byte* fStart; // First byte in this buffer
- FW_Byte* fLimit; // One past last byte of current buffer
- FW_Byte* fNext; // Current position in buffer
-
- FW_ByteCount fBytesPerChar; // Default value is sizeof(FW_Char)
- };
-
- //========================================================================================
- // CLASS FW_CMemoryReader
- //
- // A class for iterating over a buffer of characters.
- //========================================================================================
-
- class FW_CLASS_ATTR FW_CMemoryReader : public FW_CTextReader
- {
- public:
-
- virtual ~ FW_CMemoryReader();
- FW_CMemoryReader(const FW_Byte * buffer, FW_ByteCount bytes);
- FW_CMemoryReader(const FW_Char * buffer,
- FW_CharacterCount characters,
- FW_ByteCount bytesPerChar=sizeof(FW_Char));
-
- protected:
-
- virtual void DoGetNextBuffer();
- virtual void DoGetPreviousBuffer();
-
- };
-
- //========================================================================================
- // CLASS FW_CMemoryWriter
- //
- // A class for writing into a buffer of characters.
- //========================================================================================
-
- class FW_CLASS_ATTR FW_CMemoryWriter : public FW_CTextWriter
- {
- public:
-
- virtual ~ FW_CMemoryWriter();
- FW_CMemoryWriter(FW_Byte * buffer, FW_ByteCount capacity);
-
- protected:
-
- virtual void DoFlushBuffer(FW_ByteCount bytesToFlush); // Override
- virtual void DoGetNextBuffer(); // Override
-
- };
-
- //========================================================================================
- // CLASS FW_CTextReader inlines
- //========================================================================================
-
- //----------------------------------------------------------------------------------------
- // FW_CTextReader::GetByteLength
- //----------------------------------------------------------------------------------------
-
- inline FW_ByteCount FW_CTextReader::GetByteLength()
- {
- return fByteLength;
- }
-
- //----------------------------------------------------------------------------------------
- // FW_CTextReader::PeekRunAhead
- //----------------------------------------------------------------------------------------
-
- inline void FW_CTextReader::PeekRunAhead(const FW_Byte*& start, FW_ByteCount& length)
- {
- start = fNext;
- length = fLimit-fNext;
- }
-
- //----------------------------------------------------------------------------------------
- // FW_CTextReader::PeekRunBehind
- //----------------------------------------------------------------------------------------
-
- inline void FW_CTextReader::PeekRunBehind(const FW_Byte*& end, FW_ByteCount& length)
- {
- end = fNext;
- length = fNext-fStart;
- }
-
- //----------------------------------------------------------------------------------------
- // FW_CTextReader::Advance
- //----------------------------------------------------------------------------------------
-
- inline void FW_CTextReader::Advance()
- {
- this->Advance(fBytesPerChar);
- }
-
- //----------------------------------------------------------------------------------------
- // FW_CTextReader::Backup
- //----------------------------------------------------------------------------------------
-
- inline void FW_CTextReader::Backup()
- {
- this->Backup(fBytesPerChar);
- }
-
- //----------------------------------------------------------------------------------------
- // FW_CTextReader::BytesToChars
- //----------------------------------------------------------------------------------------
-
- inline FW_CharacterCount FW_CTextReader::BytesToChars(const FW_ByteCount bytes)
- {
- return bytes/fBytesPerChar;
- }
-
- //----------------------------------------------------------------------------------------
- // FW_CTextReader::CharsToBytes
- //----------------------------------------------------------------------------------------
-
- inline FW_ByteCount FW_CTextReader::CharsToBytes(FW_CharacterCount length)
- {
- return length*fBytesPerChar;
- }
-
- //----------------------------------------------------------------------------------------
- // FW_CTextReader::BytesInBlock
- //----------------------------------------------------------------------------------------
-
- inline FW_ByteCount FW_CTextReader::BytesInBlock(const FW_Byte* last, const FW_Byte* first)
- {
- return (last - first);
- }
-
- //----------------------------------------------------------------------------------------
- // FW_CTextReader::PeekByte
- //----------------------------------------------------------------------------------------
-
- inline const FW_Byte* FW_CTextReader::PeekByte() const
- {
- ClassInvariants();
-
- if (fNext>=fStart && fNext<fLimit)
- return fNext;
- else
- return NULL;
- }
-
- //----------------------------------------------------------------------------------------
- // FW_CTextReader::PreviousByte
- //----------------------------------------------------------------------------------------
- inline const FW_Byte* FW_CTextReader::PreviousByte(const FW_Byte* current, short delta)
- {
- return current - delta;
- }
-
- //========================================================================================
- // CLASS FW_CTextWriter inlines
- //========================================================================================
-
- //----------------------------------------------------------------------------------------
- // FW_CTextWriter::GetPosition
- //----------------------------------------------------------------------------------------
-
- inline FW_ByteCount FW_CTextWriter::GetPosition()
- {
- return fBufferSum + (fNext - fStart);
- }
-
- //----------------------------------------------------------------------------------------
- // FW_CTextWriter::FlushAndGetNextBuffer
- //----------------------------------------------------------------------------------------
-
- inline void FW_CTextWriter::FlushAndGetNextBuffer()
- {
- FlushBuffer(TRUE); // flush entire buffer
- DoGetNextBuffer();
- }
-
- //----------------------------------------------------------------------------------------
- // FW_CTextWriter::WritePeek
- //----------------------------------------------------------------------------------------
-
- inline void FW_CTextWriter::WritePeek(FW_Byte*& start, FW_ByteCount& length)
- {
- if (fNext >= fLimit)
- FlushAndGetNextBuffer();
- start = fNext;
- length = fLimit-fNext;
- }
-
- //----------------------------------------------------------------------------------------
- // FW_CTextWriter::WritePeekAdvance
- //----------------------------------------------------------------------------------------
-
- inline void FW_CTextWriter::WritePeekAdvance(const FW_Byte* start, FW_ByteCount bytesWritten)
- {
- FW_ASSERT(start == fNext);
- FW_ASSERT(bytesWritten <= fLimit-fNext);
- fNext += bytesWritten;
- }
-
- #if FW_LIB_EXPORT_PRAGMAS
- #pragma lib_export off
- #endif
-
- #endif
-